home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / Perl / cons.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-01  |  36.0 KB  |  1,469 lines

  1. /* $RCSfile: cons.c,v $$Revision: 4.0.1.4 $$Date: 1993/02/05 19:30:15 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log:    cons.c,v $
  9.  * Revision 4.0.1.3  1992/06/08  12:18:35  lwall
  10.  * patch20: removed implicit int declarations on funcions
  11.  * patch20: deleted some minor memory leaks
  12.  * patch20: fixed double debug break in foreach with implicit array assignment
  13.  * patch20: fixed confusion between a *var's real name and its effective name
  14.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  15.  * patch20: debugger sometimes displayed wrong source line
  16.  * patch20: various error messages have been clarified
  17.  * patch20: an eval block containing a null block or statement could dump core
  18.  * 
  19.  * Revision 4.0.1.2  91/11/05  16:15:13  lwall
  20.  * patch11: debugger got confused over nested subroutine definitions
  21.  * patch11: prepared for ctype implementations that don't define isascii()
  22.  * 
  23.  * Revision 4.0.1.1  91/06/07  10:31:15  lwall
  24.  * patch4: new copyright notice
  25.  * patch4: added global modifier for pattern matches
  26.  * 
  27.  * Revision 4.0  91/03/20  01:05:51  lwall
  28.  * 4.0 baseline.
  29.  * 
  30.  */
  31.  
  32. #include "EXTERN.h"
  33. #include "perl.h"
  34. #include "perly.h"
  35.  
  36. extern char *tokename[];
  37. extern int yychar;
  38.  
  39. static int cmd_tosave();
  40. static int arg_tosave();
  41. static int spat_tosave();
  42. static void make_cswitch();
  43. static void make_nswitch();
  44.  
  45. /* MN: No problem */
  46. static bool saw_return;
  47.  
  48. SUBR *
  49. make_sub(name,cmd)
  50. char *name;
  51. CMD *cmd;
  52. {
  53.     register SUBR *sub;
  54.     STAB *stab = stabent(name,TRUE);
  55.  
  56.     if (sub = stab_sub(stab)) {
  57.     if (dowarn) {
  58.         CMD *oldcurcmd = curcmd;
  59.  
  60.         if (cmd)
  61.         curcmd = cmd;
  62.         warn("Subroutine %s redefined",name);
  63.         curcmd = oldcurcmd;
  64.     }
  65.     if (!sub->usersub && sub->cmd) {
  66.         cmd_free(sub->cmd);
  67.         sub->cmd = Nullcmd;
  68.         afree(sub->tosave);
  69.     }
  70.     Safefree(sub);
  71.     }
  72.     Newz(101,sub,1,SUBR);
  73.     stab_sub(stab) = sub;
  74.     sub->filestab = curcmd->c_filestab;
  75.     saw_return = FALSE;
  76.     tosave = anew(Nullstab);
  77.     tosave->ary_fill = 0;    /* make 1 based */
  78.     (void)cmd_tosave(cmd,FALSE);    /* this builds the tosave array */
  79.     sub->tosave = tosave;
  80.     if (saw_return) {
  81.     struct compcmd mycompblock;
  82.  
  83.     mycompblock.comp_true = cmd;
  84.     mycompblock.comp_alt = Nullcmd;
  85.     cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,0,
  86.         Nullarg,mycompblock));
  87.     saw_return = FALSE;
  88.     cmd->c_flags |= CF_TERM;
  89.     cmd->c_head = cmd;
  90.     }
  91.     sub->cmd = cmd;
  92.     if (perldb) {
  93.     STR *str;
  94.     STR *tmpstr = str_mortal(&str_undef);
  95.  
  96.     sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr, subline);
  97.     str = str_make(buf,0);
  98.     str_cat(str,"-");
  99.     sprintf(buf,"%ld",(long)curcmd->c_line);
  100.     str_cat(str,buf);
  101.     stab_efullname(tmpstr,stab);
  102.     hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
  103.     }
  104.     Safefree(name);
  105.     return sub;
  106. }
  107.  
  108. SUBR *
  109. make_usub(name, ix, subaddr, filename)
  110. char *name;
  111. int ix;
  112. int (*subaddr)();
  113. char *filename;
  114. {
  115.     register SUBR *sub;
  116.     STAB *stab = stabent(name,allstabs);
  117.  
  118.     if (!stab)                /* unused function */
  119.     return Null(SUBR*);
  120.     if (sub = stab_sub(stab)) {
  121.     if (dowarn)
  122.         warn("Subroutine %s redefined",name);
  123.     if (!sub->usersub && sub->cmd) {
  124.         cmd_free(sub->cmd);
  125.         sub->cmd = Nullcmd;
  126.         afree(sub->tosave);
  127.     }
  128.     Safefree(sub);
  129.     }
  130.     Newz(101,sub,1,SUBR);
  131.     stab_sub(stab) = sub;
  132.     sub->filestab = fstab(filename);
  133.     sub->usersub = subaddr;
  134.     sub->userindex = ix;
  135.     return sub;
  136. }
  137.  
  138. void
  139. make_form(stab,fcmd)
  140. STAB *stab;
  141. FCMD *fcmd;
  142. {
  143.     if (stab_form(stab)) {
  144.     FCMD *tmpfcmd;
  145.     FCMD *nextfcmd;
  146.  
  147.     for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) {
  148.         nextfcmd = tmpfcmd->f_next;
  149.         if (tmpfcmd->f_expr)
  150.         arg_free(tmpfcmd->f_expr);
  151.         if (tmpfcmd->f_unparsed)
  152.         str_free(tmpfcmd->f_unparsed);
  153.         if (tmpfcmd->f_pre)
  154.         Safefree(tmpfcmd->f_pre);
  155.         Safefree(tmpfcmd);
  156.     }
  157.     }
  158.     stab_form(stab) = fcmd;
  159. }
  160.  
  161. CMD *
  162. block_head(tail)
  163. register CMD *tail;
  164. {
  165.     CMD *head;
  166.     register int opt;
  167.     register int last_opt = 0;
  168.     register STAB *last_stab = Nullstab;
  169.     register int count = 0;
  170.     register CMD *switchbeg = Nullcmd;
  171.  
  172.     if (tail == Nullcmd) {
  173.     return tail;
  174.     }
  175.     head = tail->c_head;
  176.  
  177.     for (tail = head; tail; tail = tail->c_next) {
  178.  
  179.     /* save one measly dereference at runtime */
  180.     if (tail->c_type == C_IF) {
  181.         if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next))
  182.         tail->c_flags |= CF_TERM;
  183.     }
  184.     else if (tail->c_type == C_EXPR) {
  185.         ARG *arg;
  186.  
  187.         if (tail->ucmd.acmd.ac_expr)
  188.         arg = tail->ucmd.acmd.ac_expr;
  189.         else
  190.         arg = tail->c_expr;
  191.         if (arg) {
  192.         if (arg->arg_type == O_RETURN)
  193.             tail->c_flags |= CF_TERM;
  194.         else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  195.             tail->c_flags |= CF_TERM;
  196.         }
  197.     }
  198.     if (!tail->c_next)
  199.         tail->c_flags |= CF_TERM;
  200.  
  201.     if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  202.         opt_arg(tail,1, tail->c_type == C_EXPR);
  203.  
  204.     /* now do a little optimization on case-ish structures */
  205.     switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
  206.     case CFT_ANCHOR:
  207.     case CFT_STROP:
  208.         opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
  209.         break;
  210.     case CFT_CCLASS:
  211.         opt = CFT_STROP;
  212.         break;
  213.     case CFT_NUMOP:
  214.         opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP);
  215.         if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE))
  216.         opt = 0;
  217.         break;
  218.     default:
  219.         opt = 0;
  220.     }
  221.     if (opt && opt == last_opt && tail->c_stab == last_stab)
  222.         count++;
  223.     else {
  224.         if (count >= 3) {        /* is this the breakeven point? */
  225.         if (last_opt == CFT_NUMOP)
  226.             make_nswitch(switchbeg,count);
  227.         else
  228.             make_cswitch(switchbeg,count);
  229.         }
  230.         if (opt) {
  231.         count = 1;
  232.         switchbeg = tail;
  233.         }
  234.         else
  235.         count = 0;
  236.     }
  237.     last_opt = opt;
  238.     last_stab = tail->c_stab;
  239.     }
  240.     if (count >= 3) {        /* is this the breakeven point? */
  241.     if (last_opt == CFT_NUMOP)
  242.         make_nswitch(switchbeg,count);
  243.     else
  244.         make_cswitch(switchbeg,count);
  245.     }
  246.     return head;
  247. }
  248.  
  249. /* We've spotted a sequence of CMDs that all test the value of the same
  250.  * spat.  Thus we can insert a SWITCH in front and jump directly
  251.  * to the correct one.
  252.  */
  253. static void
  254. make_cswitch(head,count)
  255. register CMD *head;
  256. int count;
  257. {
  258.     register CMD *cur;
  259.     register CMD **loc;
  260.     register int i;
  261.     register int min = 255;
  262.     register int max = 0;
  263.  
  264.     /* make a new head in the exact same spot */
  265.     New(102,cur, 1, CMD);
  266.     StructCopy(head,cur,CMD);
  267.     Zero(head,1,CMD);
  268.     head->c_head = cur->c_head;
  269.     head->c_type = C_CSWITCH;
  270.     head->c_next = cur;        /* insert new cmd at front of list */
  271.     head->c_stab = cur->c_stab;
  272.  
  273.     Newz(103,loc,258,CMD*);
  274.     loc++;                /* lie a little */
  275.     while (count--) {
  276.     if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) {
  277.         for (i = 0; i <= 255; i++) {
  278.         if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) {
  279.             loc[i] = cur;
  280.             if (i < min)
  281.             min = i;
  282.             if (i > max)
  283.             max = i;
  284.         }
  285.         }
  286.     }
  287.     else {
  288.         i = *cur->c_short->str_ptr & 255;
  289.         if (!loc[i]) {
  290.         loc[i] = cur;
  291.         if (i < min)
  292.             min = i;
  293.         if (i > max)
  294.             max = i;
  295.         }
  296.     }
  297.     cur = cur->c_next;
  298.     }
  299.     max++;
  300.     if (min > 0)
  301.     Move(&loc[min],&loc[0], max - min, CMD*);
  302.     loc--;
  303.     min--;
  304.     max -= min;
  305.     for (i = 0; i <= max; i++)
  306.     if (!loc[i])
  307.         loc[i] = cur;
  308.     Renew(loc,max+1,CMD*);    /* chop it down to size */
  309.     head->ucmd.scmd.sc_offset = min;
  310.     head->ucmd.scmd.sc_max = max;
  311.     head->ucmd.scmd.sc_next = loc;
  312. }
  313.  
  314. static void
  315. make_nswitch(head,count)
  316. register CMD *head;
  317. int count;
  318. {
  319.     register CMD *cur = head;
  320.     register CMD **loc;
  321.     register int i;
  322.     register int min = 32767;
  323.     register int max = -32768;
  324.     int origcount = count;
  325.     double value;        /* or your money back! */
  326.     short changed;        /* so triple your money back! */
  327.  
  328.     while (count--) {
  329.     i = (int)str_gnum(cur->c_short);
  330.     value = (double)i;
  331.     if (value != cur->c_short->str_u.str_nval)
  332.         return;        /* fractional values--just forget it */
  333.     changed = i;
  334.     if (changed != i)
  335.         return;        /* too big for a short */
  336.     if (cur->c_slen == O_LE)
  337.         i++;
  338.     else if (cur->c_slen == O_GE)    /* we only do < or > here */
  339.         i--;
  340.     if (i < min)
  341.         min = i;
  342.     if (i > max)
  343.         max = i;
  344.     cur = cur->c_next;
  345.     }
  346.     count = origcount;
  347.     if (max - min > count * 2 + 10)        /* too sparse? */
  348.     return;
  349.  
  350.     /* now make a new head in the exact same spot */
  351.     New(104,cur, 1, CMD);
  352.     StructCopy(head,cur,CMD);
  353.     Zero(head,1,CMD);
  354.     head->c_head = cur->c_head;
  355.     head->c_type = C_NSWITCH;
  356.     head->c_next = cur;        /* insert new cmd at front of list */
  357.     head->c_stab = cur->c_stab;
  358.  
  359.     Newz(105,loc, max - min + 3, CMD*);
  360.     loc++;
  361.     max -= min;
  362.     max++;
  363.     while (count--) {
  364.     i = (int)str_gnum(cur->c_short);
  365.     i -= min;
  366.     switch(cur->c_slen) {
  367.     case O_LE:
  368.         i++;
  369.     case O_LT:
  370.         for (i--; i >= -1; i--)
  371.         if (!loc[i])
  372.             loc[i] = cur;
  373.         break;
  374.     case O_GE:
  375.         i--;
  376.     case O_GT:
  377.         for (i++; i <= max; i++)
  378.         if (!loc[i])
  379.             loc[i] = cur;
  380.         break;
  381.     case O_EQ:
  382.         if (!loc[i])
  383.         loc[i] = cur;
  384.         break;
  385.     }
  386.     cur = cur->c_next;
  387.     }
  388.     loc--;
  389.     min--;
  390.     max++;
  391.     for (i = 0; i <= max; i++)
  392.     if (!loc[i])
  393.         loc[i] = cur;
  394.     head->ucmd.scmd.sc_offset = min;
  395.     head->ucmd.scmd.sc_max = max;
  396.     head->ucmd.scmd.sc_next = loc;
  397. }
  398.  
  399. CMD *
  400. append_line(head,tail)
  401. register CMD *head;
  402. register CMD *tail;
  403. {
  404.     if (tail == Nullcmd)
  405.     return head;
  406.     if (!tail->c_head)            /* make sure tail is well formed */
  407.     tail->c_head = tail;
  408.     if (head != Nullcmd) {
  409.     tail = tail->c_head;        /* get to start of tail list */
  410.     if (!head->c_head)
  411.         head->c_head = head;    /* start a new head list */
  412.     while (head->c_next) {
  413.         head->c_next->c_head = head->c_head;
  414.         head = head->c_next;    /* get to end of head list */
  415.     }
  416.     head->c_next = tail;        /* link to end of old list */
  417.     tail->c_head = head->c_head;    /* propagate head pointer */
  418.     }
  419.     while (tail->c_next) {
  420.     tail->c_next->c_head = tail->c_head;
  421.     tail = tail->c_next;
  422.     }
  423.     return tail;
  424. }
  425.  
  426. CMD *
  427. dodb(cur)
  428. CMD *cur;
  429. {
  430.     register CMD *cmd;
  431.     register CMD *head = cur->c_head;
  432.     STR *str;
  433.  
  434.     if (!head)
  435.     head = cur;
  436.     if (!head->c_line)
  437.     return cur;
  438.     str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE);
  439.     if (str == &str_undef || str->str_nok)
  440.     return cur;
  441.     str->str_u.str_nval = (double)head->c_line;
  442.     str->str_nok = 1;
  443.     Newz(106,cmd,1,CMD);
  444.     str_magic(str, curcmd->c_filestab, 0, Nullch, 0);
  445.     str->str_magic->str_u.str_cmd = cmd;
  446.     cmd->c_type = C_EXPR;
  447.     cmd->ucmd.acmd.ac_stab = Nullstab;
  448.     cmd->ucmd.acmd.ac_expr = Nullarg;
  449.     cmd->c_expr = make_op(O_SUBR, 2,
  450.     stab2arg(A_WORD,DBstab),
  451.     Nullarg,
  452.     Nullarg);
  453.     /*SUPPRESS 53*/
  454.     cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
  455.     cmd->c_line = head->c_line;
  456.     cmd->c_label = head->c_label;
  457.     cmd->c_filestab = curcmd->c_filestab;
  458.     cmd->c_stash = curstash;
  459.     return append_line(cmd, cur);
  460. }
  461.  
  462. CMD *
  463. make_acmd(type,stab,cond,arg)
  464. int type;
  465. STAB *stab;
  466. ARG *cond;
  467. ARG *arg;
  468. {
  469.     register CMD *cmd;
  470.  
  471.     Newz(107,cmd,1,CMD);
  472.     cmd->c_type = type;
  473.     cmd->ucmd.acmd.ac_stab = stab;
  474.     cmd->ucmd.acmd.ac_expr = arg;
  475.     cmd->c_expr = cond;
  476.     if (cond)
  477.     cmd->c_flags |= CF_COND;
  478.     if (cmdline == NOLINE)
  479.     cmd->c_line = curcmd->c_line;
  480.     else {
  481.     cmd->c_line = cmdline;
  482.     cmdline = NOLINE;
  483.     }
  484.     cmd->c_filestab = curcmd->c_filestab;
  485.     cmd->c_stash = curstash;
  486.     if (perldb)
  487.     cmd = dodb(cmd);
  488.     return cmd;
  489. }
  490.  
  491. CMD *
  492. make_ccmd(type,debuggable,arg,cblock)
  493. int type;
  494. int debuggable;
  495. ARG *arg;
  496. struct compcmd cblock;
  497. {
  498.     register CMD *cmd;
  499.  
  500.     Newz(108,cmd, 1, CMD);
  501.     cmd->c_type = type;
  502.     cmd->c_expr = arg;
  503.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  504.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  505.     if (arg)
  506.     cmd->c_flags |= CF_COND;
  507.     if (cmdline == NOLINE)
  508.     cmd->c_line = curcmd->c_line;
  509.     else {
  510.     cmd->c_line = cmdline;
  511.     cmdline = NOLINE;
  512.     }
  513.     cmd->c_filestab = curcmd->c_filestab;
  514.     cmd->c_stash = curstash;
  515.     if (perldb && debuggable)
  516.     cmd = dodb(cmd);
  517.     return cmd;
  518. }
  519.  
  520. CMD *
  521. make_icmd(type,arg,cblock)
  522. int type;
  523. ARG *arg;
  524. struct compcmd cblock;
  525. {
  526.     register CMD *cmd;
  527.     register CMD *alt;
  528.     register CMD *cur;
  529.     register CMD *head;
  530.     struct compcmd ncblock;
  531.  
  532.     Newz(109,cmd, 1, CMD);
  533.     head = cmd;
  534.     cmd->c_type = type;
  535.     cmd->c_expr = arg;
  536.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  537.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  538.     if (arg)
  539.     cmd->c_flags |= CF_COND;
  540.     if (cmdline == NOLINE)
  541.     cmd->c_line = curcmd->c_line;
  542.     else {
  543.     cmd->c_line = cmdline;
  544.     cmdline = NOLINE;
  545.     }
  546.     cmd->c_filestab = curcmd->c_filestab;
  547.     cmd->c_stash = curstash;
  548.     cur = cmd;
  549.     alt = cblock.comp_alt;
  550.     while (alt && alt->c_type == C_ELSIF) {
  551.     cur = alt;
  552.     alt = alt->ucmd.ccmd.cc_alt;
  553.     }
  554.     if (alt) {            /* a real life ELSE at the end? */
  555.     ncblock.comp_true = alt;
  556.     ncblock.comp_alt = Nullcmd;
  557.     alt = append_line(cur,make_ccmd(C_ELSE,1,Nullarg,ncblock));
  558.     cur->ucmd.ccmd.cc_alt = alt;
  559.     }
  560.     else
  561.     alt = cur;        /* no ELSE, so cur is proxy ELSE */
  562.  
  563.     cur = cmd;
  564.     while (cmd) {        /* now point everyone at the ELSE */
  565.     cur = cmd;
  566.     cmd = cur->ucmd.ccmd.cc_alt;
  567.     cur->c_head = head;
  568.     if (cur->c_type == C_ELSIF)
  569.         cur->c_type = C_IF;
  570.     if (cur->c_type == C_IF)
  571.         cur->ucmd.ccmd.cc_alt = alt;
  572.     if (cur == alt)
  573.         break;
  574.     cur->c_next = cmd;
  575.     }
  576.     if (perldb)
  577.     cur = dodb(cur);
  578.     return cur;
  579. }
  580.  
  581. void
  582. opt_arg(cmd,fliporflop,acmd)
  583. register CMD *cmd;
  584. int fliporflop;
  585. int acmd;
  586. {
  587.     register ARG *arg;
  588.     int opt = CFT_EVAL;
  589.     int sure = 0;
  590.     ARG *arg2;
  591.     int context = 0;    /* 0 = normal, 1 = before &&, 2 = before || */
  592.     int flp = fliporflop;
  593.  
  594.     if (!cmd)
  595.     return;
  596.     if (!(arg = cmd->c_expr)) {
  597.     cmd->c_flags &= ~CF_COND;
  598.     return;
  599.     }
  600.  
  601.     /* Can we turn && and || into if and unless? */
  602.  
  603.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) &&
  604.       (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
  605.     dehoist(arg,1);
  606.     arg[2].arg_type &= A_MASK;    /* don't suppress eval */
  607.     dehoist(arg,2);
  608.     cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
  609.     cmd->c_expr = arg[1].arg_ptr.arg_arg;
  610.     if (arg->arg_type == O_OR)
  611.         cmd->c_flags ^= CF_INVERT;        /* || is like unless */
  612.     arg->arg_len = 0;
  613.     free_arg(arg);
  614.     arg = cmd->c_expr;
  615.     }
  616.  
  617.     /* Turn "if (!expr)" into "unless (expr)" */
  618.  
  619.     if (!(cmd->c_flags & CF_TERM)) {        /* unless return value wanted */
  620.     while (arg->arg_type == O_NOT) {
  621.         dehoist(arg,1);
  622.         cmd->c_flags ^= CF_INVERT;        /* flip sense of cmd */
  623.         cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
  624.         free_arg(arg);
  625.         arg = cmd->c_expr;            /* here we go again */
  626.     }
  627.     }
  628.  
  629.     if (!arg->arg_len) {        /* sanity check */
  630.     cmd->c_flags |= opt;
  631.     return;
  632.     }
  633.  
  634.     /* for "cond .. cond" we set up for the initial check */
  635.  
  636.     if (arg->arg_type == O_FLIP)
  637.     context |= 4;
  638.  
  639.     /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
  640.  
  641.   morecontext:
  642.     if (arg->arg_type == O_AND)
  643.     context |= 1;
  644.     else if (arg->arg_type == O_OR)
  645.     context |= 2;
  646.     if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) {
  647.     arg = arg[flp].arg_ptr.arg_arg;
  648.     flp = 1;
  649.     if (arg->arg_type == O_AND || arg->arg_type == O_OR)
  650.         goto morecontext;
  651.     }
  652.     if ((context & 3) == 3)
  653.     return;
  654.  
  655.     if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
  656.     cmd->c_flags |= opt;
  657.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM)
  658.       && cmd->c_expr->arg_type == O_ITEM) {
  659.         arg[flp].arg_flags &= ~AF_POST;    /* prefer ++$foo to $foo++ */
  660.         arg[flp].arg_flags |= AF_PRE;    /*  if value not wanted */
  661.     }
  662.     return;                /* side effect, can't optimize */
  663.     }
  664.  
  665.     if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
  666.       arg->arg_type == O_AND || arg->arg_type == O_OR) {
  667.     if ((arg[flp].arg_type & A_MASK) == A_SINGLE) {
  668.         opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
  669.         cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str);
  670.         goto literal;
  671.     }
  672.     else if ((arg[flp].arg_type & A_MASK) == A_STAB ||
  673.       (arg[flp].arg_type & A_MASK) == A_LVAL) {
  674.         cmd->c_stab  = arg[flp].arg_ptr.arg_stab;
  675.         if (!context)
  676.         arg[flp].arg_ptr.arg_stab = Nullstab;
  677.         opt = CFT_REG;
  678.       literal:
  679.         if (!context) {    /* no && or ||? */
  680.         arg_free(arg);
  681.         cmd->c_expr = Nullarg;
  682.         }
  683.         if (!(context & 1))
  684.         cmd->c_flags |= CF_EQSURE;
  685.         if (!(context & 2))
  686.         cmd->c_flags |= CF_NESURE;
  687.     }
  688.     }
  689.     else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
  690.          arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
  691.     if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  692.         (arg[2].arg_type & A_MASK) == A_SPAT &&
  693.         arg[2].arg_ptr.arg_spat->spat_short &&
  694.         (arg->arg_type == O_SUBST || arg->arg_type == O_NSUBST ||
  695.          (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_GLOBAL) == 0 )) {
  696.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  697.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short);
  698.         cmd->c_slen  = arg[2].arg_ptr.arg_spat->spat_slen;
  699.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
  700.         !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
  701.         (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
  702.         sure |= CF_EQSURE;        /* (SUBST must be forced even */
  703.                         /* if we know it will work.) */
  704.         if (arg->arg_type != O_SUBST) {
  705.         str_free(arg[2].arg_ptr.arg_spat->spat_short);
  706.         arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
  707.         arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
  708.         }
  709.         sure |= CF_NESURE;        /* normally only sure if it fails */
  710.         if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
  711.         cmd->c_flags |= CF_FIRSTNEG;
  712.         if (context & 1) {        /* only sure if thing is false */
  713.         if (cmd->c_flags & CF_FIRSTNEG)
  714.             sure &= ~CF_NESURE;
  715.         else
  716.             sure &= ~CF_EQSURE;
  717.         }
  718.         else if (context & 2) {    /* only sure if thing is true */
  719.         if (cmd->c_flags & CF_FIRSTNEG)
  720.             sure &= ~CF_EQSURE;
  721.         else
  722.             sure &= ~CF_NESURE;
  723.         }
  724.         if (sure & (CF_EQSURE|CF_NESURE)) {    /* if we know anything*/
  725.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
  726.             opt = CFT_SCAN;
  727.         else
  728.             opt = CFT_ANCHOR;
  729.         if (sure == (CF_EQSURE|CF_NESURE)    /* really sure? */
  730.             && arg->arg_type == O_MATCH
  731.             && context & 4
  732.             && fliporflop == 1) {
  733.             spat_free(arg[2].arg_ptr.arg_spat);
  734.             arg[2].arg_ptr.arg_spat = Nullspat;    /* don't do twice */
  735.         }
  736.         else
  737.             cmd->c_spat = arg[2].arg_ptr.arg_spat;
  738.         cmd->c_flags |= sure;
  739.         }
  740.     }
  741.     }
  742.     else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
  743.          arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
  744.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  745.         if (arg[2].arg_type == A_SINGLE) {
  746.         /*SUPPRESS 594*/
  747.         char *junk = str_get(arg[2].arg_ptr.arg_str);
  748.  
  749.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  750.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_str);
  751.         cmd->c_slen  = cmd->c_short->str_cur+1;
  752.         switch (arg->arg_type) {
  753.         case O_SLT: case O_SGT:
  754.             sure |= CF_EQSURE;
  755.             cmd->c_flags |= CF_FIRSTNEG;
  756.             break;
  757.         case O_SNE:
  758.             cmd->c_flags |= CF_FIRSTNEG;
  759.             /* FALL THROUGH */
  760.         case O_SEQ:
  761.             sure |= CF_NESURE|CF_EQSURE;
  762.             break;
  763.         }
  764.         if (context & 1) {    /* only sure if thing is false */
  765.             if (cmd->c_flags & CF_FIRSTNEG)
  766.             sure &= ~CF_NESURE;
  767.             else
  768.             sure &= ~CF_EQSURE;
  769.         }
  770.         else if (context & 2) { /* only sure if thing is true */
  771.             if (cmd->c_flags & CF_FIRSTNEG)
  772.             sure &= ~CF_EQSURE;
  773.             else
  774.             sure &= ~CF_NESURE;
  775.         }
  776.         if (sure & (CF_EQSURE|CF_NESURE)) {
  777.             opt = CFT_STROP;
  778.             cmd->c_flags |= sure;
  779.         }
  780.         }
  781.     }
  782.     }
  783.     else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
  784.          arg->arg_type == O_LE || arg->arg_type == O_GE ||
  785.          arg->arg_type == O_LT || arg->arg_type == O_GT) {
  786.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  787.         if (arg[2].arg_type == A_SINGLE) {
  788.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  789.         if (dowarn) {
  790.             STR *str = arg[2].arg_ptr.arg_str;
  791.  
  792.             if ((!str->str_nok && !looks_like_number(str)))
  793.             warn("Possible use of == on string value");
  794.         }
  795.         cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
  796.         cmd->c_slen = arg->arg_type;
  797.         sure |= CF_NESURE|CF_EQSURE;
  798.         if (context & 1) {    /* only sure if thing is false */
  799.             sure &= ~CF_EQSURE;
  800.         }
  801.         else if (context & 2) { /* only sure if thing is true */
  802.             sure &= ~CF_NESURE;
  803.         }
  804.         if (sure & (CF_EQSURE|CF_NESURE)) {
  805.             opt = CFT_NUMOP;
  806.             cmd->c_flags |= sure;
  807.         }
  808.         }
  809.     }
  810.     }
  811.     else if (arg->arg_type == O_ASSIGN &&
  812.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  813.          arg[1].arg_ptr.arg_stab == defstab &&
  814.          arg[2].arg_type == A_EXPR ) {
  815.     arg2 = arg[2].arg_ptr.arg_arg;
  816.     if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
  817.         opt = CFT_GETS;
  818.         cmd->c_stab = arg2[1].arg_ptr.arg_stab;
  819.         if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) {
  820.         free_arg(arg2);
  821.         arg[2].arg_ptr.arg_arg = Nullarg;
  822.         free_arg(arg);
  823.         cmd->c_expr = Nullarg;
  824.         }
  825.     }
  826.     }
  827.     else if (arg->arg_type == O_CHOP &&
  828.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
  829.     opt = CFT_CHOP;
  830.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  831.     free_arg(arg);
  832.     cmd->c_expr = Nullarg;
  833.     }
  834.     if (context & 4)
  835.     opt |= CF_FLIP;
  836.     cmd->c_flags |= opt;
  837.  
  838.     if (cmd->c_flags & CF_FLIP) {
  839.     if (fliporflop == 1) {
  840.         arg = cmd->c_expr;    /* get back to O_FLIP arg */
  841.         New(110,arg[3].arg_ptr.arg_cmd, 1, CMD);
  842.         Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD);
  843.         New(111,arg[4].arg_ptr.arg_cmd,1,CMD);
  844.         Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD);
  845.         opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
  846.         arg->arg_len = 2;        /* this is a lie */
  847.     }
  848.     else {
  849.         if ((opt & CF_OPTIMIZE) == CFT_EVAL)
  850.         cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
  851.     }
  852.     }
  853. }
  854.  
  855. CMD *
  856. add_label(lbl,cmd)
  857. char *lbl;
  858. register CMD *cmd;
  859. {
  860.     if (cmd)
  861.     cmd->c_label = lbl;
  862.     return cmd;
  863. }
  864.  
  865. CMD *
  866. addcond(cmd, arg)
  867. register CMD *cmd;
  868. register ARG *arg;
  869. {
  870.     cmd->c_expr = arg;
  871.     cmd->c_flags |= CF_COND;
  872.     return cmd;
  873. }
  874.  
  875. CMD *
  876. addloop(cmd, arg)
  877. register CMD *cmd;
  878. register ARG *arg;
  879. {
  880.     void while_io();
  881.  
  882.     cmd->c_expr = arg;
  883.     cmd->c_flags |= CF_COND|CF_LOOP;
  884.  
  885.     if (!(cmd->c_flags & CF_INVERT))
  886.     while_io(cmd);        /* add $_ =, if necessary */
  887.  
  888.     if (cmd->c_type == C_BLOCK)
  889.     cmd->c_flags &= ~CF_COND;
  890.     else {
  891.     arg = cmd->ucmd.acmd.ac_expr;
  892.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  893.         cmd->c_flags &= ~CF_COND;  /* "do {} while" happens at least once */
  894.     if (arg && (arg->arg_flags & AF_DEPR) &&
  895.       (arg->arg_type == O_SUBR || arg->arg_type == O_DBSUBR) )
  896.         cmd->c_flags &= ~CF_COND;  /* likewise for "do subr() while" */
  897.     }
  898.     return cmd;
  899. }
  900.  
  901. CMD *
  902. invert(cmd)
  903. CMD *cmd;
  904. {
  905.     register CMD *targ = cmd;
  906.     if (targ->c_head)
  907.     targ = targ->c_head;
  908.     if (targ->c_flags & CF_DBSUB)
  909.     targ = targ->c_next;
  910.     targ->c_flags ^= CF_INVERT;
  911.     return cmd;
  912. }
  913.  
  914. void
  915. cpy7bit(d,s,l)
  916. register char *d;
  917. register char *s;
  918. register int l;
  919. {
  920.     while (l--)
  921.     *d++ = *s++ & 127;
  922.     *d = '\0';
  923. }
  924.  
  925. int
  926. yyerror(s)
  927. char *s;
  928. {
  929.     char tmpbuf[258];
  930.     char tmp2buf[258];
  931.     char *tname = tmpbuf;
  932.  
  933.     if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
  934.       oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
  935.     while (isSPACE(*oldoldbufptr))
  936.         oldoldbufptr++;
  937.     cpy7bit(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
  938.     sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
  939.     }
  940.     else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
  941.       oldbufptr != bufptr) {
  942.     while (isSPACE(*oldbufptr))
  943.         oldbufptr++;
  944.     cpy7bit(tmp2buf, oldbufptr, bufptr - oldbufptr);
  945.     sprintf(tname,"next token \"%s\"",tmp2buf);
  946.     }
  947.     else if (yychar > 256)
  948.     tname = "next token ???";
  949.     else if (!yychar)
  950.     (void)strcpy(tname,"at EOF");
  951.     else if (yychar < 32)
  952.     (void)sprintf(tname,"next char ^%c",yychar+64);
  953.     else if (yychar == 127)
  954.     (void)strcpy(tname,"at EOF");
  955.     else
  956.     (void)sprintf(tname,"next char %c",yychar);
  957. #ifdef macintosh
  958.     (void)sprintf(buf, "# %s, %s\n", s, tname);
  959.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  960.     sprintf(buf+strlen(buf),
  961.       "#  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  962.       multi_open,multi_close,multi_start);
  963.     strcpy(
  964.         MPWPosIndication(
  965.         buf+strlen(buf),
  966.         stab_val(curcmd->c_filestab)->str_ptr,
  967.         curcmd->c_line),
  968.     "\n");
  969. #else
  970.     (void)sprintf(buf, "%s in file %s at line %d, %s\n",
  971.       s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname);
  972.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  973.     sprintf(buf+strlen(buf),
  974.       "  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  975.       multi_open,multi_close,multi_start);
  976. #endif
  977.     if (in_eval)
  978.     str_cat(stab_val(stabent("@",TRUE)),buf);
  979.     else
  980.     fputs(buf,stderr);
  981.     if (++error_count >= 10)
  982.     fatal("%s has too many errors.\n",
  983.     stab_val(curcmd->c_filestab)->str_ptr);
  984. #ifdef macintosh
  985.     return 0;
  986. #endif
  987. }
  988.  
  989. void
  990. while_io(cmd)
  991. register CMD *cmd;
  992. {
  993.     register ARG *arg = cmd->c_expr;
  994.     STAB *asgnstab;
  995.  
  996.     /* hoist "while (<channel>)" up into command block */
  997.  
  998.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
  999.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1000.     cmd->c_flags |= CFT_GETS;    /* and set it to do the input */
  1001.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  1002.     if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) {
  1003.         cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$_ =" */
  1004.            stab2arg(A_LVAL,defstab), arg, Nullarg));
  1005.     }
  1006.     else {
  1007.         free_arg(arg);
  1008.         cmd->c_expr = Nullarg;
  1009.     }
  1010.     }
  1011.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
  1012.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1013.     cmd->c_flags |= CFT_INDGETS;    /* and set it to do the input */
  1014.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  1015.     free_arg(arg);
  1016.     cmd->c_expr = Nullarg;
  1017.     }
  1018.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
  1019.     if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
  1020.         asgnstab = cmd->c_stab;
  1021.     else
  1022.         asgnstab = defstab;
  1023.     cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$foo =" */
  1024.        stab2arg(A_LVAL,asgnstab), arg, Nullarg));
  1025.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1026.     }
  1027. }
  1028.  
  1029. CMD *
  1030. wopt(cmd)
  1031. register CMD *cmd;
  1032. {
  1033.     register CMD *tail;
  1034.     CMD *newtail;
  1035.     register int i;
  1036.  
  1037.     if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  1038.     opt_arg(cmd,1, cmd->c_type == C_EXPR);
  1039.  
  1040.     while_io(cmd);        /* add $_ =, if necessary */
  1041.  
  1042.     /* First find the end of the true list */
  1043.  
  1044.     tail = cmd->ucmd.ccmd.cc_true;
  1045.     if (tail == Nullcmd)
  1046.     return cmd;
  1047.     New(112,newtail, 1, CMD);    /* guaranteed continue */
  1048.     for (;;) {
  1049.     /* optimize "next" to point directly to continue block */
  1050.     if (tail->c_type == C_EXPR &&
  1051.         tail->ucmd.acmd.ac_expr &&
  1052.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1053.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1054.          (cmd->c_label &&
  1055.           strEQ(cmd->c_label,
  1056.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1057.     {
  1058.         arg_free(tail->ucmd.acmd.ac_expr);
  1059.         tail->ucmd.acmd.ac_expr = Nullarg;
  1060.         tail->c_type = C_NEXT;
  1061.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1062.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1063.         else
  1064.         tail->ucmd.ccmd.cc_alt = newtail;
  1065.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1066.     }
  1067.     else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1068.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1069.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1070.         else
  1071.         tail->ucmd.ccmd.cc_alt = newtail;
  1072.     }
  1073.     else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1074.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1075.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1076.             if (!tail->ucmd.scmd.sc_next[i])
  1077.             tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt;
  1078.         }
  1079.         else {
  1080.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1081.             if (!tail->ucmd.scmd.sc_next[i])
  1082.             tail->ucmd.scmd.sc_next[i] = newtail;
  1083.         }
  1084.     }
  1085.  
  1086.     if (!tail->c_next)
  1087.         break;
  1088.     tail = tail->c_next;
  1089.     }
  1090.  
  1091.     /* if there's a continue block, link it to true block and find end */
  1092.  
  1093.     if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1094. #ifdef macintosh
  1095.     /* Work around a code generation bug in MPW C 3.2 */
  1096.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1097.     tail = cmd->ucmd.ccmd.cc_alt;
  1098. #else
  1099.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1100.     tail = tail->c_next;
  1101. #endif
  1102.     for (;;) {
  1103.         /* optimize "next" to point directly to continue block */
  1104.         if (tail->c_type == C_EXPR &&
  1105.         tail->ucmd.acmd.ac_expr &&
  1106.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1107.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1108.          (cmd->c_label &&
  1109.           strEQ(cmd->c_label,
  1110.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1111.         {
  1112.         arg_free(tail->ucmd.acmd.ac_expr);
  1113.         tail->ucmd.acmd.ac_expr = Nullarg;
  1114.         tail->c_type = C_NEXT;
  1115.         tail->ucmd.ccmd.cc_alt = newtail;
  1116.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1117.         }
  1118.         else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1119.         tail->ucmd.ccmd.cc_alt = newtail;
  1120.         }
  1121.         else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1122.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1123.             if (!tail->ucmd.scmd.sc_next[i])
  1124.             tail->ucmd.scmd.sc_next[i] = newtail;
  1125.         }
  1126.  
  1127.         if (!tail->c_next)
  1128.         break;
  1129.         tail = tail->c_next;
  1130.     }
  1131.     /*SUPPRESS 530*/
  1132.     for ( ; tail->c_next; tail = tail->c_next) ;
  1133.     }
  1134.  
  1135.     /* Here's the real trick: link the end of the list back to the beginning,
  1136.      * inserting a "last" block to break out of the loop.  This saves one or
  1137.      * two procedure calls every time through the loop, because of how cmd_exec
  1138.      * does tail recursion.
  1139.      */
  1140.  
  1141.     tail->c_next = newtail;
  1142.     tail = newtail;
  1143.     if (!cmd->ucmd.ccmd.cc_alt)
  1144.     cmd->ucmd.ccmd.cc_alt = tail;    /* every loop has a continue now */
  1145.  
  1146. #ifndef lint
  1147.     Copy((char *)cmd, (char *)tail, 1, CMD);
  1148. #endif
  1149.     tail->c_type = C_EXPR;
  1150.     tail->c_flags ^= CF_INVERT;        /* turn into "last unless" */
  1151.     tail->c_next = tail->ucmd.ccmd.cc_true;    /* loop directly back to top */
  1152.     tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg);
  1153.     tail->ucmd.acmd.ac_stab = Nullstab;
  1154.     return cmd;
  1155. }
  1156.  
  1157. CMD *
  1158. over(eachstab,cmd)
  1159. STAB *eachstab;
  1160. register CMD *cmd;
  1161. {
  1162.     /* hoist "for $foo (@bar)" up into command block */
  1163.  
  1164.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1165.     cmd->c_flags |= CFT_ARRAY;        /* and set it to do the iteration */
  1166.     cmd->c_stab = eachstab;
  1167.     cmd->c_short = Str_new(23,0);    /* just to save a field in struct cmd */
  1168.     cmd->c_short->str_u.str_useful = -1;
  1169.  
  1170.     return cmd;
  1171. }
  1172.  
  1173. void
  1174. cmd_free(cmd)
  1175. register CMD *cmd;
  1176. {
  1177.     register CMD *tofree;
  1178.     register CMD *head = cmd;
  1179.  
  1180.     if (!cmd)
  1181.     return;
  1182.     if (cmd->c_head != cmd)
  1183.     warn("Malformed cmd links\n");
  1184.     while (cmd) {
  1185.     if (cmd->c_type != C_WHILE) {    /* WHILE block is duplicated */
  1186.         if (cmd->c_label) {
  1187.         Safefree(cmd->c_label);
  1188.         cmd->c_label = Nullch;
  1189.         }
  1190.         if (cmd->c_short) {
  1191.         str_free(cmd->c_short);
  1192.         cmd->c_short = Nullstr;
  1193.         }
  1194.         if (cmd->c_expr) {
  1195.         arg_free(cmd->c_expr);
  1196.         cmd->c_expr = Nullarg;
  1197.         }
  1198.     }
  1199.     switch (cmd->c_type) {
  1200.     case C_WHILE:
  1201.     case C_BLOCK:
  1202.     case C_ELSE:
  1203.     case C_IF:
  1204.         if (cmd->ucmd.ccmd.cc_true) {
  1205.         cmd_free(cmd->ucmd.ccmd.cc_true);
  1206.         cmd->ucmd.ccmd.cc_true = Nullcmd;
  1207.         }
  1208.         break;
  1209.     case C_EXPR:
  1210.         if (cmd->ucmd.acmd.ac_expr) {
  1211.         arg_free(cmd->ucmd.acmd.ac_expr);
  1212.         cmd->ucmd.acmd.ac_expr = Nullarg;
  1213.         }
  1214.         break;
  1215.     }
  1216.     tofree = cmd;
  1217.     cmd = cmd->c_next;
  1218.     if (tofree != head)        /* to get Saber to shut up */
  1219.         Safefree(tofree);
  1220.     if (cmd && cmd == head)        /* reached end of while loop */
  1221.         break;
  1222.     }
  1223.     Safefree(head);
  1224. }
  1225.  
  1226. void
  1227. arg_free(arg)
  1228. register ARG *arg;
  1229. {
  1230.     register int i;
  1231.  
  1232.     if (!arg)
  1233.     return;
  1234.     for (i = 1; i <= arg->arg_len; i++) {
  1235.     switch (arg[i].arg_type & A_MASK) {
  1236.     case A_NULL:
  1237.         if (arg->arg_type == O_TRANS) {
  1238.         Safefree(arg[i].arg_ptr.arg_cval);
  1239.         arg[i].arg_ptr.arg_cval = Nullch;
  1240.         }
  1241.         break;
  1242.     case A_LEXPR:
  1243.         if (arg->arg_type == O_AASSIGN &&
  1244.           arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) {
  1245.         char *name = 
  1246.           stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab);
  1247.  
  1248.         if (strnEQ("_GEN_",name, 5))    /* array for foreach */
  1249.             hdelete(defstash,name,strlen(name));
  1250.         }
  1251.         /* FALL THROUGH */
  1252.     case A_EXPR:
  1253.         arg_free(arg[i].arg_ptr.arg_arg);
  1254.         arg[i].arg_ptr.arg_arg = Nullarg;
  1255.         break;
  1256.     case A_CMD:
  1257.         cmd_free(arg[i].arg_ptr.arg_cmd);
  1258.         arg[i].arg_ptr.arg_cmd = Nullcmd;
  1259.         break;
  1260.     case A_WORD:
  1261.     case A_STAB:
  1262.     case A_LVAL:
  1263.     case A_READ:
  1264.     case A_GLOB:
  1265.     case A_ARYLEN:
  1266.     case A_LARYLEN:
  1267.     case A_ARYSTAB:
  1268.     case A_LARYSTAB:
  1269.         break;
  1270.     case A_SINGLE:
  1271.     case A_DOUBLE:
  1272.     case A_BACKTICK:
  1273.         str_free(arg[i].arg_ptr.arg_str);
  1274.         arg[i].arg_ptr.arg_str = Nullstr;
  1275.         break;
  1276.     case A_SPAT:
  1277.         spat_free(arg[i].arg_ptr.arg_spat);
  1278.         arg[i].arg_ptr.arg_spat = Nullspat;
  1279.         break;
  1280.     }
  1281.     }
  1282.     free_arg(arg);
  1283. }
  1284.  
  1285. void
  1286. spat_free(spat)
  1287. register SPAT *spat;
  1288. {
  1289.     register SPAT *sp;
  1290.     HENT *entry;
  1291.  
  1292.     if (!spat)
  1293.     return;
  1294.     if (spat->spat_runtime) {
  1295.     arg_free(spat->spat_runtime);
  1296.     spat->spat_runtime = Nullarg;
  1297.     }
  1298.     if (spat->spat_repl) {
  1299.     arg_free(spat->spat_repl);
  1300.     spat->spat_repl = Nullarg;
  1301.     }
  1302.     if (spat->spat_short) {
  1303.     str_free(spat->spat_short);
  1304.     spat->spat_short = Nullstr;
  1305.     }
  1306.     if (spat->spat_regexp) {
  1307.     regfree(spat->spat_regexp);
  1308.     spat->spat_regexp = Null(REGEXP*);
  1309.     }
  1310.  
  1311.     /* now unlink from spat list */
  1312.  
  1313.     for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) {
  1314.     register HASH *stash;
  1315.     STAB *stab = (STAB*)entry->hent_val;
  1316.  
  1317.     if (!stab)
  1318.         continue;
  1319.     stash = stab_hash(stab);
  1320.     if (!stash || stash->tbl_spatroot == Null(SPAT*))
  1321.         continue;
  1322.     if (stash->tbl_spatroot == spat)
  1323.         stash->tbl_spatroot = spat->spat_next;
  1324.     else {
  1325.         for (sp = stash->tbl_spatroot;
  1326.           sp && sp->spat_next != spat;
  1327.           sp = sp->spat_next)
  1328.         /*SUPPRESS 530*/
  1329.         ;
  1330.         if (sp)
  1331.         sp->spat_next = spat->spat_next;
  1332.     }
  1333.     }
  1334.     Safefree(spat);
  1335. }
  1336.  
  1337. /* Recursively descend a command sequence and push the address of any string
  1338.  * that needs saving on recursion onto the tosave array.
  1339.  */
  1340.  
  1341. static int
  1342. cmd_tosave(cmd,willsave)
  1343. register CMD *cmd;
  1344. int willsave;                /* willsave passes down the tree */
  1345. {
  1346.     register CMD *head = cmd;
  1347.     int shouldsave = FALSE;        /* shouldsave passes up the tree */
  1348.     int tmpsave;
  1349.     register CMD *lastcmd = Nullcmd;
  1350.  
  1351.     while (cmd) {
  1352.     if (cmd->c_expr)
  1353.         shouldsave |= arg_tosave(cmd->c_expr,willsave);
  1354.     switch (cmd->c_type) {
  1355.     case C_WHILE:
  1356.         if (cmd->ucmd.ccmd.cc_true) {
  1357.         tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1358.  
  1359.         /* Here we check to see if the temporary array generated for
  1360.          * a foreach needs to be localized because of recursion.
  1361.          */
  1362.         if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) {
  1363.             if (lastcmd &&
  1364.               lastcmd->c_type == C_EXPR &&
  1365.               lastcmd->c_expr) {
  1366.             ARG *arg = lastcmd->c_expr;
  1367.  
  1368.             if (arg->arg_type == O_ASSIGN &&
  1369.                 arg[1].arg_type == A_LEXPR &&
  1370.                 arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY &&
  1371.                 strnEQ("_GEN_",
  1372.                   stab_name(
  1373.                 arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab),
  1374.                   5)) {    /* array generated for foreach */
  1375.                 (void)localize(arg);
  1376.             }
  1377.             }
  1378.  
  1379.             /* in any event, save the iterator */
  1380.  
  1381.             if (cmd->c_short)  /* Better safe than sorry */
  1382.             (void)apush(tosave,cmd->c_short);
  1383.         }
  1384.         shouldsave |= tmpsave;
  1385.         }
  1386.         break;
  1387.     case C_BLOCK:
  1388.     case C_ELSE:
  1389.     case C_IF:
  1390.         if (cmd->ucmd.ccmd.cc_true)
  1391.         shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1392.         break;
  1393.     case C_EXPR:
  1394.         if (cmd->ucmd.acmd.ac_expr)
  1395.         shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave);
  1396.         break;
  1397.     }
  1398.     lastcmd = cmd;
  1399.     cmd = cmd->c_next;
  1400.     if (cmd && cmd == head)        /* reached end of while loop */
  1401.         break;
  1402.     }
  1403.     return shouldsave;
  1404. }
  1405.  
  1406. static int
  1407. arg_tosave(arg,willsave)
  1408. register ARG *arg;
  1409. int willsave;
  1410. {
  1411.     register int i;
  1412.     int shouldsave = FALSE;
  1413.  
  1414.     for (i = arg->arg_len; i >= 1; i--) {
  1415.     switch (arg[i].arg_type & A_MASK) {
  1416.     case A_NULL:
  1417.         break;
  1418.     case A_LEXPR:
  1419.     case A_EXPR:
  1420.         shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave);
  1421.         break;
  1422.     case A_CMD:
  1423.         shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave);
  1424.         break;
  1425.     case A_WORD:
  1426.     case A_STAB:
  1427.     case A_LVAL:
  1428.     case A_READ:
  1429.     case A_GLOB:
  1430.     case A_ARYLEN:
  1431.     case A_SINGLE:
  1432.     case A_DOUBLE:
  1433.     case A_BACKTICK:
  1434.         break;
  1435.     case A_SPAT:
  1436.         shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat);
  1437.         break;
  1438.     }
  1439.     }
  1440.     switch (arg->arg_type) {
  1441.     case O_RETURN:
  1442.     saw_return = TRUE;
  1443.     break;
  1444.     case O_EVAL:
  1445.     case O_SUBR:
  1446.     shouldsave = TRUE;
  1447.     break;
  1448.     }
  1449.     if (willsave && arg->arg_ptr.arg_str)
  1450.     (void)apush(tosave,arg->arg_ptr.arg_str);
  1451.     return shouldsave;
  1452. }
  1453.  
  1454. static int
  1455. spat_tosave(spat)
  1456. register SPAT *spat;
  1457. {
  1458.     int shouldsave = FALSE;
  1459.  
  1460.     if (spat->spat_runtime)
  1461.     shouldsave |= arg_tosave(spat->spat_runtime,FALSE);
  1462.     if (spat->spat_repl) {
  1463.     shouldsave |= arg_tosave(spat->spat_repl,FALSE);
  1464.     }
  1465.  
  1466.     return shouldsave;
  1467. }
  1468.  
  1469.